/*
Copyright (C) 2015 Marien Raat

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <enemyManager.h>
#include <math.h>
#include <iostream>

#define VEC_LENGTH(vec) (sqrt(pow(vec.x, 2.0) + pow(vec.y, 2.0)))

EnemyManager::EnemyManager(sf::Vector2u screenSize)
    : upOrDown(0, 1), xValueDist(0, screenSize.x),
      yValueDist(0, screenSize.y)
{
    this->screenSize = screenSize;
#ifndef OS_WIN
    randomDevice = new std::random_device;
    mt = new std::mt19937((*randomDevice)());
#else
    mt = new std::mt19937(time(0));
#endif

    rotationD = new std::uniform_real_distribution<double>
        (0.0, (2.0 * PI));
    radius = new std::uniform_real_distribution<double>(1.0, pow(50, (1.0 / 10.0)));

    enemies = new Enemy[ammountOfEnemies];
    for (int i = 0; i < ammountOfEnemies; i++) {
        createNewEnemyAt(i);
    }

    // Load textures
    textures = new sf::Texture[5];
    textures[0].loadFromFile("art/Bacteria2.png");
    textures[1].loadFromFile("art/Bacteria.png");
    textures[2].loadFromFile("art/Bacteria3.png");
    textures[3].loadFromFile("art/Bacteria4.png");
    textures[4].loadFromFile("art/Bacteria5.png");
}

bool EnemyManager::update(Player *player)
{
    for (int i = 0; i < ammountOfEnemies; i++)
        enemies[i].update();

    // Check collisions
    sf::Vector2f pPosition = player->getPosition();
    float playerRadius = player->getRadius();
    for (int i = 0; i < ammountOfEnemies; i++) {
        sf::Vector2f distance = pPosition - enemies[i].position;
        if (VEC_LENGTH(distance) <  playerRadius
            + enemies[i].radius) {
            if (enemies[i].radius <= playerRadius) {
                player->addCell(enemies[i].radius);
            } else {
                return true;
            }
            
            createNewEnemyAt(i);
        }
        sf::Vector2f ePosition = enemies[i].position;
        if (ePosition.x < -200.0 ||
            ePosition.x > screenSize.x + 200.0 ||
            ePosition.y < -200.0 ||
            ePosition.y > screenSize.y + 200.0) {
            createNewEnemyAt(i);
        }
    }
    return false;
}

void EnemyManager::draw(sf::RenderWindow *window)
{
    for (int i = 0; i < ammountOfEnemies; i++)
        enemies[i].draw(window, textures);
}

void EnemyManager::createNewEnemyAt(int index)
{
    sf::Vector2f position;
    float rotation = (*rotationD)(*mt);
    sf::Vector2f velocity =
        sf::Vector2f(cos(rotation), sin(rotation)) * 3.0f;
    if (upOrDown(*mt)) {
        position.x = xValueDist(*mt);
        position.y = velocity.y > 0 ?
            -0.1f * screenSize.y : 1.1f * screenSize.y;
    } else {
        position.y = yValueDist(*mt);
        position.x = velocity.x > 0 ?
            -0.1f * screenSize.x : 1.1f * screenSize.x;
    }
    float radiusE = pow((*radius)(*mt), (10.0 / 1.0));
    enemies[index].setEnemy(position, velocity, radiusE);
}
